//使用ts实现，由一系列（x,y）坐标的数据，按照x的值排序并去重， 利用线性插值，创建等距的 x 坐标，步长是由用户设置的点数决定，要求多少个点，结果长度就是多少，进行插值，计算y的平均数 得到y坐标，最终得到一系列的（x,y）数据。
// 平均值计算
// 去重和排序：去除重复的 x 值并对数据点按 x 值排序。
// 生成等距 x 坐标：根据用户设置的点数计算步长，并生成这些等距的 x 坐标。
// 线性插值：对生成的等距 x 坐标进行插值计算 y 值。
// 计算平均值：计算插值后 y 值的平均数。

export interface Point {
  x: number;
  y: number;
  sn : string;
}

// 获取线性插值统计结果
export function GetPointInterpolated(points: Point[], numberOfPoints: number,aggregateMode:number, showMode:number, isYSum:boolean) {
  console.log(isYSum)
  const sortedPoints = removeDuplicatesAndSort(points);
  if (sortedPoints.length < 2) {
    throw new Error("At least two points are required for interpolation.");
  }
  const xMin = sortedPoints[0].x;
  const xMax = sortedPoints[sortedPoints.length - 1].x;

  //按照设备进行分组
  let group = {}
  sortedPoints.map((item,index)=>{
    if(!group.hasOwnProperty(item.sn)){
      // @ts-ignore
      group[item.sn] = []
    }
    // @ts-ignore
    (group[item.sn]).push(item)
  })

  // 生成等距 x 坐标
  const equidistantX = generateEquidistantX(xMin, xMax, numberOfPoints);

  let max:number|null = null
  let min:number|null = null

  let result = []
  for (let key in group){
    // @ts-ignore
    const {xys,ymax, ymin} = getInterpolateY(group[key],equidistantX,aggregateMode,showMode,isYSum)
    result.push({
      sn: key,
      // xs:equidistantX,
      xys:xys,
      ymax:ymax,
      ymin:ymin
    })
    if(max == null){
      max = ymax
    }
    if(min == null){
      min = ymin
    }
    //@ts-ignore
    if(ymax >max ){
      max = ymax
    }
    //@ts-ignore
    if(ymin < min ){
      min = ymin
    }

  }
  return {
    computeResult:result,
    max:min ? max:0,
    min:min ? min:0,
    xMin: xMin,
    xMax: xMax,
  }
}

// 去重和排序
function removeDuplicatesAndSort(points: Point[]): Point[] {
  const uniquePoints = Array.from(new Map(points.map(p => [p.x, p])).values());
  return uniquePoints.sort((a, b) => a.x - b.x);
}

// 生成等距 x 坐标
function generateEquidistantX(xMin: number, xMax: number, numberOfPoints: number): number[] {
  const step = (xMax - xMin) / (numberOfPoints - 1);
  return Array.from({ length: numberOfPoints }, (_, i) => xMin + i * step);
}

// 找到最近的已知点的索引
function findNearestPointsIndex(sortedPoints: Point[], x: number): [number, number] {
  const len = sortedPoints.length
  for (let i = 0; i < len - 1; i++) {
    const p0 = sortedPoints[i];
    const p1 = sortedPoints[i + 1];
    if (x >= p0.x && x <= p1.x) {
      return [i, i + 1];
    }
  }
  // 如果 x 不在已知点的范围内，找最近的两个点
  return [0, len-1];
}

function getInterpolateY(points: Point[], equidistantX: Array<number>,aggregateMode:number, showMode:number, isYSum:boolean){
  const lenxEquidistant = equidistantX.length
  let ys: Array<number> = []
  let xys: Array<Array<number>> = []
  let max :number | null= null
  let min :number | null= null

  let sum = 0

  for (let i = 0; i < lenxEquidistant-1; i++) {
    const xStart = equidistantX[i]
    const xEnd = equidistantX[i+1]
    let yEach : number | null = null
    if (aggregateMode == 1) {
      yEach = averageYInInterval(points, xStart, xEnd, showMode,isYSum)
    } else if(aggregateMode == 2){   //累加
      yEach = accumulateYInInterval(points, xStart, xEnd, showMode,isYSum)
    }else {
      yEach = maxYInInterval(points, xStart, xEnd, showMode,isYSum)
    }
    //ys.push(yEach)

    let thisy;
    if(yEach != null){
      sum += yEach
      if(isYSum){
        thisy = sum
      }else{
        thisy = yEach
      }
      xys.push([equidistantX[i],thisy])
      if(max == null){
        max = thisy
      }
      if(min == null){
        min = thisy
      }
      if(thisy >max ){
        max = thisy
      }
      if(thisy < min ){
        min = thisy
      }
    }
  }
  return {
    // ys:ys,
    ymax:max ? max : 0,
    ymin:min ? min : 0,
    xys:xys,
  }
}

function averageYInInterval(points: Point[], xStart:number, xEnd:number, showMode:number,isYSum:boolean){
  var sumY : number | null = null
  var count = 0
  const lenX = points.length
  if(lenX <= 1){
    return 0
  }
  for (let i = 0; i < lenX-1; i++) {
    if( points[i].x >= xStart && points[i].x <= xEnd) {
      if(sumY == null){
        sumY = 0
      }
      sumY += points[i].y
      count++
    }
  }
  let thisinterpolatedY : number | null = null

  // 计算平均值
  if (count > 0) {
    if(sumY != null){
      thisinterpolatedY = sumY / count
    }
  } else {
    // if (showMode == 0) {
    //     // 如果该范围内x没有点  则去寻找两边最近的点
    //     // 找到距离插值点最近的两个原始数据点索引
    //     const nearest = findNearestPointsIndex(points ,xStart)
    //     const leftIdx = nearest[0]
    //     const rightIdx = nearest[1]
    //     if(leftIdx == rightIdx){
    //         thisinterpolatedY =  0
    //     }else{
    //         // 计算插值点在两个原始点之间的位置比例
    //         const t = (xStart - points[leftIdx].x) / (points[rightIdx].x - points[leftIdx].x)
    //         // 插值计算
    //         const  interpolatedValue = points[leftIdx].y + t*(points[rightIdx].y-points[leftIdx].y)
    //         thisinterpolatedY = interpolatedValue
    //     }
    // }
  }
  return thisinterpolatedY
}

function accumulateYInInterval(points: Point[], xStart:number, xEnd:number, showMode:number,isYSum:boolean){
  var accuY :number|null = null
  var count  = 0
  const lenX = points.length
  if(lenX <= 1){
    return 0
  }
  for (let i = 0; i < lenX-1; i++) {
    if( points[i].x >= xStart && points[i].x < xEnd) {
      if(accuY == null){
        accuY = 0
      }
      accuY += Number(points[i].y)
      count++
    }
  }
  return accuY
}

// maxYInInterval 计算在区间 [xStart, xEnd] 内 y 的最大值
function maxYInInterval(points: Point[], xStart:number, xEnd:number, showMode:number,isYSum:boolean) {
  var maxY :number|null = null
  var count  = 0
  const lenX = points.length
  if(lenX <= 1){
    return 0
  }
  for (let i = 0; i < lenX-1; i++) {
    if( points[i].x >= xStart && points[i].x <= xEnd) {
      if(maxY == null){
        maxY = points[i].y
      }
      if (points[i].y >= maxY) {
        maxY = points[i].y
      }
      count++
    }
  }
  let thisinterpolatedY :number|null = null
  if (count > 0) {
    thisinterpolatedY = maxY!
  } else {
    // if (showMode == 0){
    //     // 找到距离插值点最近的两个原始数据点
    //     const nearest = findNearestPointsIndex(points ,xStart)
    //     const leftIdx = nearest[0]
    //     const rightIdx = nearest[1]
    //     if(leftIdx == rightIdx){
    //         thisinterpolatedY =  0
    //     }else{
    //         // 计算插值点在两个原始点之间的位置比例
    //         const t = (xStart - points[leftIdx].x) / (points[rightIdx].x - points[leftIdx].x)
    //         // 插值计算
    //         const interpolatedValue =  points[leftIdx].y + t*(points[rightIdx].y-points[leftIdx].y)
    //         thisinterpolatedY = interpolatedValue
    //     }
    // }
  }
  return thisinterpolatedY
}
